﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

namespace Utilities
{
    public static class ReflectionOnly
    {
        #region Custom Attributes

        public static CustomAttributeData GetAttribute(MemberInfo member, string attributeName)
        {
            IList<CustomAttributeData> customAttributes = CustomAttributeData.GetCustomAttributes(member);

            return customAttributes.Where(a => a.Constructor.DeclaringType.Name == attributeName + "Attribute").SingleOrDefault();
        }

        public static bool IsAttributeDefined(MemberInfo member, string attributeName)
        {
            return GetAttribute(member, attributeName) != null;
        }

        public static object GetAttributeValue(MemberInfo member, string attributeName, string memberName)
        {
            CustomAttributeData attributeData = GetAttribute(member, attributeName);

            return GetAttributeValue(attributeData, memberName);
        }

        public static object GetAttributeValue(CustomAttributeData attributeData, string memberName)
        {
            PreCondition.RequireNotNull(attributeData, "attributeData");

            if (string.IsNullOrEmpty(memberName)) // Get constructor argument. Assume single value
            {
                CustomAttributeTypedArgument argument = attributeData.ConstructorArguments.SingleOrDefault();

                if (argument != null)
                {
                    return argument.Value;
                }
            }
            else
            {
                CustomAttributeNamedArgument argument = attributeData.NamedArguments.Where(a => a.MemberInfo.Name == memberName).SingleOrDefault();

                if (argument != null)
                {
                    return argument.TypedValue.Value;
                }
            }

            return null;
        }

        public static T GetAttributeValue<T>(MemberInfo member, string attributeName, string memberName) where T : class
        {
            return (T)GetAttributeValue(member, attributeName, memberName);
        }

        public static T GetAttributeValue<T>(CustomAttributeData attribute, string memberName) where T : class
        {
            return (T)GetAttributeValue(attribute, memberName);
        }

        #endregion

        public static IList<Tuple<string, object>> GetEnumerationItems(Type enumeration)
        {
            IList<Tuple<string, object>> list = new List<Tuple<string, object>>();
            FieldInfo[] fields = enumeration.GetFields();

            foreach (var field in fields)
            {
                if (field.Name.Equals("value__"))
                {
                    continue;
                }

                list.Add(new Tuple<string,object>(field.Name, field.GetRawConstantValue()));
            }

            return list;
        }
    }
}
